@@ -0,0 +1,51 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+from __future__ import division |
|
4 |
+ |
|
5 |
+import random |
|
6 |
+ |
|
7 |
+from utils.algorithm.b64 import b64_decrypt, b64_encrypt |
|
8 |
+from utils.algorithm.rsalg import rsa_decrypt, rsa_encrypt |
|
9 |
+from utils.error.response_utils import response |
|
10 |
+ |
|
11 |
+ |
|
12 |
+CIPHER_ALGORITHM = ('B64', 'RSA') |
|
13 |
+ |
|
14 |
+CIPHER_PREFIX = { |
|
15 |
+ 'B64': 'alg1', |
|
16 |
+ 'RSA': 'alg2', |
|
17 |
+} |
|
18 |
+ |
|
19 |
+ |
|
20 |
+def encrypt(request): |
|
21 |
+ plaintext = request.POST.get('plaintext', '') |
|
22 |
+ |
|
23 |
+ alg = random.choice(CIPHER_ALGORITHM) |
|
24 |
+ |
|
25 |
+ if alg == 'B64': |
|
26 |
+ ciphertext = b64_encrypt(plaintext) |
|
27 |
+ elif alg == 'RSA': |
|
28 |
+ ciphertext = rsa_encrypt(plaintext) |
|
29 |
+ else: |
|
30 |
+ ciphertext = plaintext |
|
31 |
+ |
|
32 |
+ return response(200, data={ |
|
33 |
+ 'ciphertext': u'%s+%s' % (CIPHER_PREFIX.get(alg, ''), ciphertext), |
|
34 |
+ }) |
|
35 |
+ |
|
36 |
+ |
|
37 |
+def decrypt(request): |
|
38 |
+ ciphertext = request.POST.get('ciphertext', '') |
|
39 |
+ |
|
40 |
+ alg, ciphertext = ciphertext.split('+', 1) |
|
41 |
+ |
|
42 |
+ if alg == CIPHER_PREFIX['B64']: |
|
43 |
+ plaintext = b64_decrypt(ciphertext) |
|
44 |
+ elif alg == CIPHER_PREFIX['RSA']: |
|
45 |
+ plaintext = rsa_decrypt(ciphertext) |
|
46 |
+ else: |
|
47 |
+ plaintext = ciphertext |
|
48 |
+ |
|
49 |
+ return response(200, data={ |
|
50 |
+ 'plaintext': plaintext, |
|
51 |
+ }) |
@@ -0,0 +1,33 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+from __future__ import division |
|
4 |
+ |
|
5 |
+from mch.models import BrandInfo, DistributorInfo, ModelInfo |
|
6 |
+from utils.error.response_utils import response |
|
7 |
+ |
|
8 |
+ |
|
9 |
+def brands_list(request): |
|
10 |
+ brands = BrandInfo.objects.filter(status=True) |
|
11 |
+ brands = [brand.data for brand in brands] |
|
12 |
+ |
|
13 |
+ return response(200, data={ |
|
14 |
+ 'brands': brands, |
|
15 |
+ }) |
|
16 |
+ |
|
17 |
+ |
|
18 |
+def models_list(request): |
|
19 |
+ models = ModelInfo.objects.filter(status=True) |
|
20 |
+ models = [model.data for model in models] |
|
21 |
+ |
|
22 |
+ return response(200, data={ |
|
23 |
+ 'models': models, |
|
24 |
+ }) |
|
25 |
+ |
|
26 |
+ |
|
27 |
+def distributors_list(request): |
|
28 |
+ distributors = DistributorInfo.objects.filter(status=True) |
|
29 |
+ distributors = [distributor.data for distributor in distributors] |
|
30 |
+ |
|
31 |
+ return response(200, data={ |
|
32 |
+ 'distributors': distributors, |
|
33 |
+ }) |
@@ -4,6 +4,7 @@ from django.conf.urls import url |
||
4 | 4 |
|
5 | 5 |
from account import views as account_views |
6 | 6 |
from account import tourguide_views |
7 |
+from api import encrypt_views, mch_views |
|
7 | 8 |
from box import views as box_views |
8 | 9 |
from geo import views as geo_views |
9 | 10 |
from group import views as group_views |
@@ -181,3 +182,15 @@ urlpatterns += [ |
||
181 | 182 |
urlpatterns += [ |
182 | 183 |
url(r'^box/loginqr$', box_views.login_qrcode_api, name='login_qrcode_api'), # 二维码登录 |
183 | 184 |
] |
185 |
+ |
|
186 |
+# Kodo |
|
187 |
+urlpatterns += [ |
|
188 |
+ url(r'^brands$', mch_views.brands_list, name='brands_list'), |
|
189 |
+ url(r'^models$', mch_views.models_list, name='models_list'), |
|
190 |
+ url(r'^distributors$', mch_views.distributors_list, name='distributors_list'), |
|
191 |
+] |
|
192 |
+ |
|
193 |
+urlpatterns += [ |
|
194 |
+ url(r'^encrypt$', encrypt_views.encrypt, name='encrypt'), |
|
195 |
+ url(r'^decrypt$', encrypt_views.decrypt, name='decrypt'), |
|
196 |
+] |
@@ -0,0 +1,22 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+from django.contrib import admin |
|
4 |
+ |
|
5 |
+from mch.models import BrandInfo, DistributorInfo, ModelInfo |
|
6 |
+ |
|
7 |
+ |
|
8 |
+class BrandInfoAdmin(admin.ModelAdmin): |
|
9 |
+ list_display = ('brand_id', 'brand_name', 'brand_descr', 'position', 'status', 'created_at', 'updated_at') |
|
10 |
+ |
|
11 |
+ |
|
12 |
+class ModelInfoAdmin(admin.ModelAdmin): |
|
13 |
+ list_display = ('model_id', 'model_name', 'model_descr', 'position', 'status', 'created_at', 'updated_at') |
|
14 |
+ |
|
15 |
+ |
|
16 |
+class DistributorInfoAdmin(admin.ModelAdmin): |
|
17 |
+ list_display = ('distributor_id', 'distributor_name', 'distributor_descr', 'position', 'status', 'created_at', 'updated_at') |
|
18 |
+ |
|
19 |
+ |
|
20 |
+admin.site.register(BrandInfo, BrandInfoAdmin) |
|
21 |
+admin.site.register(ModelInfo, ModelInfoAdmin) |
|
22 |
+admin.site.register(DistributorInfo, DistributorInfoAdmin) |
@@ -0,0 +1,8 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+from __future__ import unicode_literals |
|
3 |
+ |
|
4 |
+from django.apps import AppConfig |
|
5 |
+ |
|
6 |
+ |
|
7 |
+class MchConfig(AppConfig): |
|
8 |
+ name = 'mch' |
@@ -0,0 +1,68 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+# Generated by Django 1.11.3 on 2017-12-30 13:37 |
|
3 |
+from __future__ import unicode_literals |
|
4 |
+ |
|
5 |
+from django.db import migrations, models |
|
6 |
+import shortuuidfield.fields |
|
7 |
+ |
|
8 |
+ |
|
9 |
+class Migration(migrations.Migration): |
|
10 |
+ |
|
11 |
+ initial = True |
|
12 |
+ |
|
13 |
+ dependencies = [ |
|
14 |
+ ] |
|
15 |
+ |
|
16 |
+ operations = [ |
|
17 |
+ migrations.CreateModel( |
|
18 |
+ name='BrandInfo', |
|
19 |
+ fields=[ |
|
20 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|
21 |
+ ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')), |
|
22 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')), |
|
23 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')), |
|
24 |
+ ('brand_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='\u54c1\u724c\u552f\u4e00\u6807\u8bc6', max_length=22, unique=True)), |
|
25 |
+ ('brand_name', models.CharField(blank=True, help_text='\u54c1\u724c\u540d\u79f0', max_length=255, null=True, verbose_name='brand_name')), |
|
26 |
+ ('brand_descr', models.TextField(blank=True, help_text='\u54c1\u724c\u63cf\u8ff0', max_length=255, null=True, verbose_name='brand_descr')), |
|
27 |
+ ('position', models.IntegerField(default=1, help_text='\u6392\u5e8f', verbose_name='position')), |
|
28 |
+ ], |
|
29 |
+ options={ |
|
30 |
+ 'verbose_name': '\u54c1\u724c\u4fe1\u606f', |
|
31 |
+ 'verbose_name_plural': '\u54c1\u724c\u4fe1\u606f', |
|
32 |
+ }, |
|
33 |
+ ), |
|
34 |
+ migrations.CreateModel( |
|
35 |
+ name='DistributorInfo', |
|
36 |
+ fields=[ |
|
37 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|
38 |
+ ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')), |
|
39 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')), |
|
40 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')), |
|
41 |
+ ('distributor_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', max_length=22, unique=True)), |
|
42 |
+ ('distributor_name', models.CharField(blank=True, help_text='\u7ecf\u9500\u5546\u540d\u79f0', max_length=255, null=True, verbose_name='distributor_name')), |
|
43 |
+ ('distributor_descr', models.TextField(blank=True, help_text='\u7ecf\u9500\u5546\u63cf\u8ff0', max_length=255, null=True, verbose_name='distributor_descr')), |
|
44 |
+ ('position', models.IntegerField(default=1, help_text='\u6392\u5e8f', verbose_name='position')), |
|
45 |
+ ], |
|
46 |
+ options={ |
|
47 |
+ 'verbose_name': '\u7ecf\u9500\u5546\u4fe1\u606f', |
|
48 |
+ 'verbose_name_plural': '\u7ecf\u9500\u5546\u4fe1\u606f', |
|
49 |
+ }, |
|
50 |
+ ), |
|
51 |
+ migrations.CreateModel( |
|
52 |
+ name='ModelInfo', |
|
53 |
+ fields=[ |
|
54 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|
55 |
+ ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')), |
|
56 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')), |
|
57 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')), |
|
58 |
+ ('model_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='\u578b\u53f7\u552f\u4e00\u6807\u8bc6', max_length=22, unique=True)), |
|
59 |
+ ('model_name', models.CharField(blank=True, help_text='\u578b\u53f7\u540d\u79f0', max_length=255, null=True, verbose_name='model_name')), |
|
60 |
+ ('model_descr', models.TextField(blank=True, help_text='\u578b\u53f7\u63cf\u8ff0', max_length=255, null=True, verbose_name='model_descr')), |
|
61 |
+ ('position', models.IntegerField(default=1, help_text='\u6392\u5e8f', verbose_name='position')), |
|
62 |
+ ], |
|
63 |
+ options={ |
|
64 |
+ 'verbose_name': '\u578b\u53f7\u4fe1\u606f', |
|
65 |
+ 'verbose_name_plural': '\u578b\u53f7\u4fe1\u606f', |
|
66 |
+ }, |
|
67 |
+ ), |
|
68 |
+ ] |
@@ -0,0 +1,75 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+from django.db import models |
|
4 |
+from django.utils.translation import ugettext_lazy as _ |
|
5 |
+from models_ext import BaseModelMixin |
|
6 |
+from shortuuidfield import ShortUUIDField |
|
7 |
+ |
|
8 |
+ |
|
9 |
+class BrandInfo(BaseModelMixin): |
|
10 |
+ brand_id = ShortUUIDField(_(u'brand_id'), max_length=32, help_text=u'品牌唯一标识', db_index=True, unique=True) |
|
11 |
+ brand_name = models.CharField(_(u'brand_name'), max_length=255, blank=True, null=True, help_text=u'品牌名称') |
|
12 |
+ brand_descr = models.TextField(_(u'brand_descr'), max_length=255, blank=True, null=True, help_text=u'品牌描述') |
|
13 |
+ |
|
14 |
+ position = models.IntegerField(_(u'position'), default=1, help_text=u'排序') |
|
15 |
+ |
|
16 |
+ class Meta: |
|
17 |
+ verbose_name = _(u'品牌信息') |
|
18 |
+ verbose_name_plural = _(u'品牌信息') |
|
19 |
+ |
|
20 |
+ def __unicode__(self): |
|
21 |
+ return unicode(self.pk) |
|
22 |
+ |
|
23 |
+ @property |
|
24 |
+ def data(self): |
|
25 |
+ return { |
|
26 |
+ 'brand_id': self.brand_id, |
|
27 |
+ 'brand_name': self.brand_name, |
|
28 |
+ 'brand_descr': self.brand_descr, |
|
29 |
+ } |
|
30 |
+ |
|
31 |
+ |
|
32 |
+class ModelInfo(BaseModelMixin): |
|
33 |
+ model_id = ShortUUIDField(_(u'model_id'), max_length=32, help_text=u'型号唯一标识', db_index=True, unique=True) |
|
34 |
+ model_name = models.CharField(_(u'model_name'), max_length=255, blank=True, null=True, help_text=u'型号名称') |
|
35 |
+ model_descr = models.TextField(_(u'model_descr'), max_length=255, blank=True, null=True, help_text=u'型号描述') |
|
36 |
+ |
|
37 |
+ position = models.IntegerField(_(u'position'), default=1, help_text=u'排序') |
|
38 |
+ |
|
39 |
+ class Meta: |
|
40 |
+ verbose_name = _(u'型号信息') |
|
41 |
+ verbose_name_plural = _(u'型号信息') |
|
42 |
+ |
|
43 |
+ def __unicode__(self): |
|
44 |
+ return unicode(self.pk) |
|
45 |
+ |
|
46 |
+ @property |
|
47 |
+ def data(self): |
|
48 |
+ return { |
|
49 |
+ 'model_id': self.model_id, |
|
50 |
+ 'model_name': self.model_name, |
|
51 |
+ 'model_descr': self.model_descr, |
|
52 |
+ } |
|
53 |
+ |
|
54 |
+ |
|
55 |
+class DistributorInfo(BaseModelMixin): |
|
56 |
+ distributor_id = ShortUUIDField(_(u'distributor_id'), max_length=32, help_text=u'经销商唯一标识', db_index=True, unique=True) |
|
57 |
+ distributor_name = models.CharField(_(u'distributor_name'), max_length=255, blank=True, null=True, help_text=u'经销商名称') |
|
58 |
+ distributor_descr = models.TextField(_(u'distributor_descr'), max_length=255, blank=True, null=True, help_text=u'经销商描述') |
|
59 |
+ |
|
60 |
+ position = models.IntegerField(_(u'position'), default=1, help_text=u'排序') |
|
61 |
+ |
|
62 |
+ class Meta: |
|
63 |
+ verbose_name = _(u'经销商信息') |
|
64 |
+ verbose_name_plural = _(u'经销商信息') |
|
65 |
+ |
|
66 |
+ def __unicode__(self): |
|
67 |
+ return unicode(self.pk) |
|
68 |
+ |
|
69 |
+ @property |
|
70 |
+ def data(self): |
|
71 |
+ return { |
|
72 |
+ 'distributor_id': self.distributor_id, |
|
73 |
+ 'distributor_name': self.distributor_name, |
|
74 |
+ 'distributor_descr': self.distributor_descr, |
|
75 |
+ } |
@@ -0,0 +1,7 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+from __future__ import unicode_literals |
|
3 |
+ |
|
4 |
+from django.test import TestCase |
|
5 |
+ |
|
6 |
+ |
|
7 |
+# Create your tests here. |
@@ -0,0 +1,7 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+from __future__ import unicode_literals |
|
3 |
+ |
|
4 |
+from django.shortcuts import render |
|
5 |
+ |
|
6 |
+ |
|
7 |
+# Create your views here. |
@@ -46,10 +46,12 @@ INSTALLED_APPS = ( |
||
46 | 46 |
'django_rlog', |
47 | 47 |
'django_uniapi', |
48 | 48 |
'django_we', |
49 |
+ 'djadmin', |
|
49 | 50 |
'api', |
50 | 51 |
'account', |
51 | 52 |
'box', |
52 | 53 |
'group', |
54 |
+ 'mch', |
|
53 | 55 |
'message', |
54 | 56 |
'miniapp', |
55 | 57 |
'operation', |
@@ -6,6 +6,7 @@ Pillow==4.3.0 |
||
6 | 6 |
StatusCode==1.0.0 |
7 | 7 |
TimeConvert==1.4.1 |
8 | 8 |
cryptography==1.5.2 |
9 |
+django-admin==1.1.0 |
|
9 | 10 |
django-curtail-uuid==1.0.0 |
10 | 11 |
django-detect==1.0.5 |
11 | 12 |
django-file-md5==1.0.1 |
@@ -20,7 +21,7 @@ django-rlog==1.0.7 |
||
20 | 21 |
django-shortuuidfield==0.1.3 |
21 | 22 |
django-six==1.0.4 |
22 | 23 |
django-uniapi==1.0.0 |
23 |
-django-we==1.0.16 |
|
24 |
+django-we==1.1.2 |
|
24 | 25 |
djangorestframework==3.7.2 |
25 | 26 |
furl==1.0.1 |
26 | 27 |
hiredis==0.2.0 |
@@ -38,7 +39,7 @@ pywe-sign==1.0.6 |
||
38 | 39 |
pywe-xml==1.0.0 |
39 | 40 |
qiniu==7.1.9 |
40 | 41 |
redis==2.10.6 |
41 |
-redis-extensions==1.1.3 |
|
42 |
+redis-extensions==1.1.6 |
|
42 | 43 |
requests==2.18.4 |
43 | 44 |
rlog==0.3 |
44 | 45 |
shortuuid==0.5.0 |
@@ -0,0 +1,13 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+import base64 |
|
4 |
+ |
|
5 |
+from CodeConvert import CodeConvert as cc |
|
6 |
+ |
|
7 |
+ |
|
8 |
+def b64_encrypt(plaintext): |
|
9 |
+ return base64.urlsafe_b64encode(cc.Convert2Utf8(plaintext)) |
|
10 |
+ |
|
11 |
+ |
|
12 |
+def b64_decrypt(ciphertext): |
|
13 |
+ return cc.Convert2Unicode(base64.urlsafe_b64decode(cc.Convert2Utf8(ciphertext))) |
@@ -0,0 +1,18 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+import base64 |
|
4 |
+ |
|
5 |
+import rsa |
|
6 |
+from CodeConvert import CodeConvert as cc |
|
7 |
+ |
|
8 |
+ |
|
9 |
+pubkey = rsa.PublicKey(7733936986002684982484845608354489436048239676995253266549456282870195715569430535348099548536388503919509506510435040149560886821029985877148893951171111, 65537) |
|
10 |
+privkey = rsa.PrivateKey(7733936986002684982484845608354489436048239676995253266549456282870195715569430535348099548536388503919509506510435040149560886821029985877148893951171111, 65537, 316971401565576878144472516350155768882090601834219605321449556369521730928872332388800749109622843453327077688969025635980606763507018292148749534091473, 4517492317789178911663214752269837474466539823144998211438927363654134055916886851, 1711997816918835594017245862832442114582648667392542139046338517030653261) |
|
11 |
+ |
|
12 |
+ |
|
13 |
+def rsa_encrypt(plaintext): |
|
14 |
+ return base64.urlsafe_b64encode(rsa.encrypt(cc.Convert2Utf8(plaintext), pubkey)) |
|
15 |
+ |
|
16 |
+ |
|
17 |
+def rsa_decrypt(ciphertext): |
|
18 |
+ return rsa.decrypt(base64.urlsafe_b64decode(cc.Convert2Utf8(ciphertext)), privkey) |